package org.jeecg.modules.wlhy.report.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.mchange.lang.LongUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.enums.ReportPlatformEnum;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.LngLonUtil;
import org.jeecg.modules.third.amap.dto.GpsDTO;
import org.jeecg.modules.third.amap.dto.MapDirectionDTO;
import org.jeecg.modules.third.amap.service.AmapService;
import org.jeecg.modules.third.jg.report.freight.information.constant.enums.AhUploadStatusEnum;
import org.jeecg.modules.third.jg.report.freight.information.constant.enums.ReportDocTypeEnum;
import org.jeecg.modules.third.jg.report.freight.information.dto.AppInfoDTO;
import org.jeecg.modules.third.jg.report.freight.information.dto.DriverDTO;
import org.jeecg.modules.third.jg.report.freight.information.dto.VehicleDTO;
import org.jeecg.modules.third.jg.report.freight.information.dto.financial.FinancialDTO;
import org.jeecg.modules.third.jg.report.freight.information.dto.shippingnote.ActualCarrierInfo;
import org.jeecg.modules.third.jg.report.freight.information.dto.shippingnote.AhShippingNoteDTO;
import org.jeecg.modules.third.jg.report.freight.information.dto.shippingnote.ShippingNoteDTO;
import org.jeecg.modules.third.jg.report.freight.information.model.R;
import org.jeecg.modules.third.jg.report.freight.information.service.AhReportPlatformService;
import org.jeecg.modules.third.openapi.WaybillRouteService;
import org.jeecg.modules.wlhy.bill.entity.HyShippingNoteBill;
import org.jeecg.modules.wlhy.bill.service.IHyShippingNoteBillService;
import org.jeecg.modules.wlhy.company.entity.HyCompanyConfig;
import org.jeecg.modules.wlhy.customer.entity.HyCustomerAddressReceive;
import org.jeecg.modules.wlhy.customer.entity.HyCustomerAddressSend;
import org.jeecg.modules.wlhy.hyconfig.entity.HyConfig;
import org.jeecg.modules.wlhy.hydriver.entity.HyDriver;
import org.jeecg.modules.wlhy.hydriver.entity.HyDriverReport;
import org.jeecg.modules.wlhy.hydriver.service.IHyDriverReportService;
import org.jeecg.modules.wlhy.hydriver.service.IHyDriverService;
import org.jeecg.modules.wlhy.hyvehicle.entity.HyVehicle;
import org.jeecg.modules.wlhy.hyvehicle.entity.HyVehicleReport;
import org.jeecg.modules.wlhy.hyvehicle.entity.HyVehicleType;
import org.jeecg.modules.wlhy.hyvehicle.service.IHyVehicleReportService;
import org.jeecg.modules.wlhy.hyvehicle.service.IHyVehicleService;
import org.jeecg.modules.wlhy.order.entity.HyOrder;
import org.jeecg.modules.wlhy.order.service.IHyOrderService;
import org.jeecg.modules.wlhy.report.IReportService;
import org.jeecg.modules.wlhy.setting.service.IHySettingService;
import org.jeecg.modules.wlhy.shipping.constant.ShippingPayStatus;
import org.jeecg.modules.wlhy.shipping.constant.ShippingStatus;
import org.jeecg.modules.wlhy.shipping.entity.HyShippingNote;
import org.jeecg.modules.wlhy.shipping.entity.WaybillRouteVO;
import org.jeecg.modules.wlhy.shipping.service.IHyShippingNoteService;
import org.jeecg.modules.wlhy.utils.HyCfgUtil;
import org.jeecg.modules.wlhy.utils.HyConfigUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
@Slf4j
public class AhReportService implements IReportService {
    @Resource
    private BaseReportService baseReportService;

    @Resource
    private IHyDriverService driverService;

    @Resource
    private IHyVehicleService vehicleService;

    @Resource
    private IHyDriverReportService hyDriverReportService;

    @Resource
    private IHyVehicleReportService vehicleReportService;

    @Resource
    private AhReportPlatformService ahReportPlatformService;

    @Autowired
    private WaybillRouteService waybillRouteService;

    @Autowired
    private IHyShippingNoteService hyShippingNoteService;

    @Autowired
    private IHyShippingNoteBillService hyShippingNoteBillService;

    @Autowired
    private IHySettingService settingService;

    @Autowired
    private IHyOrderService orderService;

    @Autowired
    private AmapService amapService;

    @Override
    public ReportPlatformEnum getReportType() {
        return ReportPlatformEnum.REPORT_PLATFORM_AH;
    }

    @Override
    public void checkReport() {
        //安徽监管平台
        if(!HyCfgUtil.isUsed2("anhui_report")){
            throw new JeecgBootException("安徽监管平台未配置参数!");
        }
    }

    @Override
    public Result setReportInfo(HyCompanyConfig hyCompanyConfig) {

        if (StrUtil.isEmpty(hyCompanyConfig.getReportUrl()) || StrUtil.isEmpty(hyCompanyConfig.getReportUsername())
         || StrUtil.isEmpty(hyCompanyConfig.getReportPassword()) || StrUtil.isEmpty(hyCompanyConfig.getReportPublickey())) {
            return Result.error("安徽监管平台未配置参数!");
        }

        ahReportPlatformService.setReportInfo(hyCompanyConfig.getReportUrl(),
                hyCompanyConfig.getReportUsername(),
                hyCompanyConfig.getReportPassword(),
                hyCompanyConfig.getReportPublickey(),
                hyCompanyConfig.getReportAppid(),
                hyCompanyConfig.getReportAppkey(),
                hyCompanyConfig.getReportAppsender(),
                hyCompanyConfig.getReportApprelease());
        return Result.ok("设置成功");
    }

    @Override
    public AppInfoDTO getAppInfo() {
        return ahReportPlatformService.getAppInfo();
    }

    @Override
    public boolean report(HyShippingNote hyShippingNote) {
        return false;
    }

    @Override
    public Result reportShippingNote(HyShippingNote hyShippingNote) {
        Result result = checkDriverAndVehicle(hyShippingNote);
        if (!result.getCode().equals(CommonConstant.SC_OK_200)) {
            return result;
        }

        Result step1Result = this.uploadShippingNoteStep1(hyShippingNote);
        if (!step1Result.getCode().equals(CommonConstant.SC_OK_200)) {
            return step1Result;
        }

        Result step2Result = this.uploadShippingNoteStep2(hyShippingNote);
        if (!step2Result.getCode().equals(CommonConstant.SC_OK_200)) {
            return step2Result;
        }

        Result step3Result = this.uploadShippingNoteStep3(hyShippingNote);
        if (!step3Result.getCode().equals(CommonConstant.SC_OK_200)) {
            return step3Result;
        }

        return Result.OK();
    }

    @Override
    public Result reportCapitalFlow(HyShippingNote hyShippingNote) {
        Result result = checkDriverAndVehicle(hyShippingNote);
        if (!result.getCode().equals(CommonConstant.SC_OK_200)) {
            return result;
        }

        return this.uploadCapitalFlow(hyShippingNote.getId());
    }

    //上报运单和资金流水前，先确认司机、车辆的上传状态
    private Result checkDriverAndVehicle(HyShippingNote hyShippingNote) {

        String driverId = hyShippingNote.getDriverId();
        String vehicleId = hyShippingNote.getVehicleId();
        if (StrUtil.isEmpty(driverId)) {
            return Result.error("当前运单司机信息不存在");
        }

        if (StrUtil.isEmpty(vehicleId)) {
            return Result.error("当前运单车辆信息不存在");
        }

        //自动上报司机和车辆配置
        String autoUpload = HyCfgUtil.getCfgItem2("anhui_report","auto_upload");

        boolean bDriverUploadStatus = this.hyDriverReportService.checkUploadStatus(driverId, hyShippingNote.getCompanyId(),
                ReportPlatformEnum.REPORT_PLATFORM_AH.getCode());
        if (!bDriverUploadStatus) {
            if (StrUtil.isEmpty(autoUpload) || !autoUpload.equals("1")) {
                return Result.error("请先同步司机数据");
            }
            log.warn("司机未上报安徽监管，开始同步司机数据, 司机ID：{}", driverId);
            Result dResult = this.reportDriver(driverId, hyShippingNote.getCompanyId());
            if (!dResult.getCode().equals(CommonConstant.SC_OK_200)) {
                return dResult;
            }
        }

        boolean bVehicleUploadStatus = this.vehicleReportService.checkUploadStatus(vehicleId, hyShippingNote.getCompanyId(),
                ReportPlatformEnum.REPORT_PLATFORM_AH.getCode());
        if (!bVehicleUploadStatus) {
            if (StrUtil.isEmpty(autoUpload) || !autoUpload.equals("1")) {
                return Result.error("请先同步车辆数据");
            }
            log.warn("车辆未上报安徽监管，开始同步车辆数据, 车辆ID：{}", vehicleId);
            Result vResult = this.reportVehicle(vehicleId, hyShippingNote.getCompanyId());
            if (!vResult.getCode().equals(CommonConstant.SC_OK_200)) {
                return vResult;
            }
        }

        return Result.OK();
    }


    public Result uploadCapitalFlow(String shippingId){

        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("shipping_id", shippingId);
        List<HyShippingNoteBill> shippingNoteBills = hyShippingNoteBillService.list(queryWrapper);

        if (CollectionUtils.isEmpty(shippingNoteBills)) {
            return Result.error("未找到对应数据");
        }

        HyShippingNote hyShippingNote = hyShippingNoteService.getById(shippingId);
        if (!hyShippingNote.getUploadStatus().equals(AhUploadStatusEnum.UPLOAD_STEP3_SUCCESS.getStatus())) {
            return Result.error("请先上传运单数据");
        }

        if (!hyShippingNote.getShippingPayStatus().equals(ShippingPayStatus.支付完成.getValue())) {
            return Result.error("该运单未支付完成");
        }

        FinancialDTO financialDTO = baseReportService.getFinancialDTO(shippingNoteBills,hyShippingNote);
        String jsonString = JSONObject.toJSONString(financialDTO);

        String reporDocType = ReportDocTypeEnum.REPORT_DOC_TYPE_WLHY_ZJ.getCode();
        ReportDocTypeEnum reportDocTypeEnum = ReportDocTypeEnum.getReportDocTypeEnumByVal(reporDocType);
        try {
            //安徽资金流水延时3秒上报
            Thread.sleep(3000);
            String reportResult = ahReportPlatformService.sendReport(reportDocTypeEnum, jsonString, hyShippingNote.getShippingNoteNumber());
            if(StringUtils.isNotEmpty(reportResult)){
                R result = JSON.parseObject(reportResult, R.class);
                boolean res =  result.getCode() == 1001 && result.isSuccess() ?  true : false;
                for(HyShippingNoteBill shippingNoteBillDb :  shippingNoteBills){
                    shippingNoteBillDb.setUploadStatus(res ?  "1" : "2");
                    shippingNoteBillDb.setReportFailureReason(res ?  "" : result.getMsg()+result.getData());
                    shippingNoteBillDb.setUploadDate(new Date());
                    shippingNoteBillDb.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_AH.getCode());
                }
                hyShippingNoteBillService.updateBatchById(shippingNoteBills);
                return res ? Result.OK("上报成功") : Result.error(result.getMsg());
            }else{
                throw new JeecgBootException("未知异常");
            }
        }catch (Exception e){
            e.printStackTrace();
            for(HyShippingNoteBill shippingNoteBillDb :  shippingNoteBills){
                shippingNoteBillDb.setUploadStatus("2");
                shippingNoteBillDb.setReportFailureReason(e.getMessage());
                shippingNoteBillDb.setUploadDate(new Date());
                shippingNoteBillDb.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_AH.getCode());
            }
            hyShippingNoteBillService.updateBatchById(shippingNoteBills);
        }
        return Result.error("上报数据异常");
    }


    /**
     * 平台上报电子运单 第一步
     *
     * @param hyShippingNote
     * @return
     */
    public Result uploadShippingNoteStep1(HyShippingNote hyShippingNote) {

        HyShippingNote ShippingNoteDb = hyShippingNoteService.getById(hyShippingNote.getId());
        if (ShippingNoteDb == null) {
            throw new JeecgBootException("未找到对应数据");
        }

        String needPay = HyCfgUtil.getCfgItem2("anhui_report","need_pay");
        if (StrUtil.isNotEmpty(needPay)) {
            if (!ShippingNoteDb.getShippingPayStatus().equals(ShippingPayStatus.支付完成.getValue())) {
                return Result.error("该运单未支付完成");
            }
        }

        if ("1".equals(ShippingNoteDb.getUploadStatus())) {
            return Result.error("该运单已上报，请勿重复上报");
        }

        //第1步成功了就不用上传了
        if (StrUtil.isNotEmpty(ShippingNoteDb.getUploadStatus()) && !ShippingNoteDb.getUploadStatus().equals("0")
         && (Integer.valueOf(ShippingNoteDb.getUploadStatus()).intValue() <= AhUploadStatusEnum.UPLOAD_STEP1_SUCCESS.getCode().intValue())) {
            return Result.OK();
        }

        //时效判断 运单生成时间<运单发货时间<运单实际收货时间
        if (ShippingNoteDb.getStatusDtReceive().after(ShippingNoteDb.getStatusDtLoading())
                || ShippingNoteDb.getStatusDtLoading().after(ShippingNoteDb.getStatusDtUnloading())) {
            ShippingNoteDb.setUploadStatus(AhUploadStatusEnum.UPLOAD_STEP1_ERROR.getStatus());
            ShippingNoteDb.setUploadDate(new Date());
            ShippingNoteDb.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_AH.getCode());
            ShippingNoteDb.setReportFailureReason("该运单时效存在错误，必须满足:运单创建时间<运单装货时间<运单卸货时间。");
            this.hyShippingNoteService.updateById(ShippingNoteDb);
            return Result.error("该运单时效存在错误，必须满足:运单接单时间<运单装货时间<运单卸货时间。");
        }

        //超载判断
        HyVehicle hyVehicle = this.vehicleService.getById(ShippingNoteDb.getVehicleId());
        if (ShippingNoteDb.getGoodsWeightLoading().compareTo(hyVehicle.getVehicleTonnage()) > 0 ) {
            ShippingNoteDb.setUploadStatus(AhUploadStatusEnum.UPLOAD_STEP1_ERROR.getStatus());
            ShippingNoteDb.setUploadDate(new Date());
            ShippingNoteDb.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_AH.getCode());
            ShippingNoteDb.setReportFailureReason("货物重量超过车辆核定载质量，货物重量: "+ShippingNoteDb.getGoodsWeightLoading()+"车辆核定载质量:"+hyVehicle.getVehicleTonnage());
            this.hyShippingNoteService.updateById(ShippingNoteDb);
            log.error("安徽监管上报超载 货物重量 {} > 核定载质量 {}", ShippingNoteDb.getGoodsWeightLoading(), hyVehicle.getVehicleTonnage());
            return Result.error("货物重量超过车辆核定载质量，货物重量:" + ShippingNoteDb.getGoodsWeightLoading() + " ,车辆核定载质量:" + hyVehicle.getVehicleTonnage());
        }

        //安徽分段上传运单1
        ShippingNoteDTO shippingNoteDTO = baseReportService.shippingNoteTOShippingNoteDTO(ShippingNoteDb, hyShippingNote.getCompanyId());
        //安徽ShippingNote
        AhShippingNoteDTO ahShippingNoteDTO = new AhShippingNoteDTO();
        BeanUtil.copyProperties(shippingNoteDTO, ahShippingNoteDTO, true);

        //运距 Distance （公里）
        //hyShippingNote.getTransportationDistance()一般情况下是没值的。如果轨迹有问题，可以通过在shippingnote表中手工指定公里数
        double distance = 0d;
        if (StrUtil.isEmpty(hyShippingNote.getTransportationDistance())) {
            //如果开启表示真实轨迹，0关闭表示用模拟轨迹的公里数
            String vehicleTrackSwitch = this.settingService.getSettingValueByTag2("vehicle_track_switch");
            if ("1".equals(vehicleTrackSwitch)) {
                String startTime = DateUtils.dateTimeToString(hyShippingNote.getStatusDtLoading());
                String endTime = DateUtils.dateTimeToString(hyShippingNote.getStatusDtUnloading());
                String vehicleColor = StringUtils.isNotEmpty(hyVehicle.getVehiclePlateColorCode()) ? hyVehicle.getVehiclePlateColorCode() : "2";
                WaybillRouteVO waybillRouteVO = waybillRouteService.getWaybillRoute(hyVehicle.getVehicleNumber(), vehicleColor, startTime, endTime, "GCJ02");
                //如果轨迹是空或者是0km无法进行上报
                if (StrUtil.isEmpty(waybillRouteVO.getMileage()) || 0 == Double.valueOf(waybillRouteVO.getMileage()).intValue()) {
                    return Result.error("无法获取运单的运输距离，请检查中交车辆轨迹。");
                }

                log.info("安徽运单上报，中交轨迹公里数{}", waybillRouteVO.getMileage());
                distance = new BigDecimal(waybillRouteVO.getMileage()).setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue();
            } else {
                HyOrder hyOrder = this.orderService.getById(ShippingNoteDb.getOrderId());
                MapDirectionDTO mapDirectionDTO = this.amapService.getMapGpsOrder(hyOrder);
                if (ObjectUtil.isEmpty(mapDirectionDTO)) {
                    return Result.error("模拟轨迹数据不正确");
                }

                log.info("安徽运单上报，模拟轨迹公里数{}", mapDirectionDTO.getDistance());
                distance = new BigDecimal(mapDirectionDTO.getDistance()).setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue();
            }
        } else {
            distance = new BigDecimal(hyShippingNote.getTransportationDistance()).setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue();
        }

        //Modified at 2023-10-24 for 安徽监管只提醒不作为异常率
        //平均运费判断 平均运费不能大于 0.5 元/吨每公里（大件运输除外）
//        BigDecimal avgPrice = (new BigDecimal(ahShippingNoteDTO.getTotalMonetaryAmount()))
//                .divide(new BigDecimal(distance), 3, BigDecimal.ROUND_HALF_UP)
//                .divide(ShippingNoteDb.getGoodsWeightLoading(),3, BigDecimal.ROUND_HALF_UP).setScale(3, BigDecimal.ROUND_HALF_UP);
//        if (avgPrice.compareTo(new BigDecimal(0.5)) > 0) {
//            ShippingNoteDb.setUploadStatus(AhUploadStatusEnum.UPLOAD_STEP1_ERROR.getStatus());
//            ShippingNoteDb.setUploadDate(new Date());
//            ShippingNoteDb.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_AH.getCode());
//            ShippingNoteDb.setReportFailureReason("该运单运费金额存在错误，平均运费不能大于0.5 元/吨每公里。");
//            this.hyShippingNoteService.updateById(ShippingNoteDb);
//            log.warn("该运单运费平均金额存在错误, {} -> {} {} {}",
//                    avgPrice, ahShippingNoteDTO.getTotalMonetaryAmount(), distance, ShippingNoteDb.getGoodsWeightLoading());
//            return Result.error("该运单运费金额存在错误，平均运费不能大于0.5 元/吨每公里。");
//        }

        ahShippingNoteDTO.setDistance(String.valueOf(distance));
        //是否是大件运输 IsLargeSize 0非  1是
        ahShippingNoteDTO.setIsLargeSize("0");
        String postJsonString = JSONUtil.toJsonStr(ahShippingNoteDTO);

        String reporDocType = ReportDocTypeEnum.REPORT_DOC_TYPE_WLHY_YD1.getCode();
        ReportDocTypeEnum reportDocTypeEnum = ReportDocTypeEnum.getReportDocTypeEnumByVal(reporDocType);

        try{
            String reportResult = ahReportPlatformService.sendReport(reportDocTypeEnum, postJsonString, hyShippingNote.getShippingNoteNumber());
            if (StringUtils.isNotEmpty(reportResult)) {
                R result = JSON.parseObject(reportResult, R.class);
                boolean res = result.getCode() == 1001 && result.isSuccess() ? true : false;
                //上传运单第一步
                ShippingNoteDb.setUploadStatus(res ? AhUploadStatusEnum.UPLOAD_STEP1_SUCCESS.getStatus() : AhUploadStatusEnum.UPLOAD_STEP1_ERROR.getStatus());
                ShippingNoteDb.setReportFailureReason(res ? "" : result.getMsg()+result.getData());
                ShippingNoteDb.setUploadDate(new Date());
                ShippingNoteDb.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_AH.getCode());
                hyShippingNoteService.updateById(ShippingNoteDb);

                Thread.sleep(2000);
                return res ? Result.OK("上报成功") : Result.error(result.getMsg());
            } else {
                throw new JeecgBootException("安徽监管平台响应报文错误");
            }
        } catch (Exception e) {
            e.printStackTrace();
            ShippingNoteDb.setUploadStatus(AhUploadStatusEnum.UPLOAD_STEP1_ERROR.getStatus());
            ShippingNoteDb.setReportFailureReason(e.getMessage());
            ShippingNoteDb.setUploadDate(new Date());
            ShippingNoteDb.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_AH.getCode());
            hyShippingNoteService.updateById(ShippingNoteDb);
        }

        return Result.error("上报数据传输失败");
    }


    /**
     * 平台上报电子运单 第二步
     *
     * @param hyShippingNote
     * @return
     */
    public Result uploadShippingNoteStep2(HyShippingNote hyShippingNote) {

        HyShippingNote ShippingNoteDb = hyShippingNoteService.getById(hyShippingNote.getId());
        if (ShippingNoteDb == null) {
            throw new JeecgBootException("未找到对应运单数据");
        }

        //第2步成功了就不用上传了
        if (StrUtil.isNotEmpty(ShippingNoteDb.getUploadStatus())
         && (Integer.valueOf(ShippingNoteDb.getUploadStatus()).intValue() <= AhUploadStatusEnum.UPLOAD_STEP2_SUCCESS.getCode().intValue())) {
            return Result.OK();
        }

        ShippingNoteDTO shippingNoteDTO = baseReportService.shippingNoteTOShippingNoteDTOAhStep2(ShippingNoteDb);
        String postJsonString = JSONUtil.toJsonStr(shippingNoteDTO);
        String reporDocType = ReportDocTypeEnum.REPORT_DOC_TYPE_WLHY_YD2.getCode();
        ReportDocTypeEnum reportDocTypeEnum = ReportDocTypeEnum.getReportDocTypeEnumByVal(reporDocType);

        try{
            String reportResult = ahReportPlatformService.sendReport(reportDocTypeEnum, postJsonString, hyShippingNote.getShippingNoteNumber());
            if (StringUtils.isNotEmpty(reportResult)) {
                R result = JSON.parseObject(reportResult, R.class);
                boolean res = result.getCode() == 1001 && result.isSuccess() ? true : false;
                //上传运单第二步
                ShippingNoteDb.setUploadStatus(res ? AhUploadStatusEnum.UPLOAD_STEP2_SUCCESS.getStatus() : AhUploadStatusEnum.UPLOAD_STEP2_ERROR.getStatus());
                ShippingNoteDb.setReportFailureReason(res ? "" : result.getMsg()+result.getData());
                ShippingNoteDb.setUploadDate(new Date());
                ShippingNoteDb.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_AH.getCode());
                hyShippingNoteService.updateById(ShippingNoteDb);

                Thread.sleep(2000);
                return res ? Result.OK("上报成功") : Result.error(result.getMsg());
            } else {
                throw new JeecgBootException("安徽监管平台响应报文错误");
            }
        } catch (Exception e) {
            e.printStackTrace();
            ShippingNoteDb.setUploadStatus(AhUploadStatusEnum.UPLOAD_STEP2_ERROR.getStatus());
            ShippingNoteDb.setReportFailureReason(e.getMessage());
            ShippingNoteDb.setUploadDate(new Date());
            ShippingNoteDb.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_AH.getCode());
            hyShippingNoteService.updateById(ShippingNoteDb);
        }

        return Result.error("上报数据传输失败");
    }


    /**
     * 平台上报电子运单 第三步
     *
     * @param hyShippingNote
     * @return
     */
    public Result uploadShippingNoteStep3(HyShippingNote hyShippingNote) {

        HyShippingNote ShippingNoteDb = hyShippingNoteService.getById(hyShippingNote.getId());
        if (ShippingNoteDb == null) {
            throw new JeecgBootException("未找到对应运单数据");
        }

        //第3步成功了就不用上传了
        if (StrUtil.isNotEmpty(ShippingNoteDb.getUploadStatus())
                && (Integer.valueOf(ShippingNoteDb.getUploadStatus()).intValue() <= AhUploadStatusEnum.UPLOAD_STEP3_SUCCESS.getCode().intValue())) {
            return Result.OK();
        }

        //装卸货时间冲突判断，取半年内的运单做对比
        //为什么会在运单3这里判断，因为目前来看安徽监管运单1和运单2上报后其实不算真正的运单上报，只有当运单3上报后才会在监管平台显示该运单
        //所以这里拦截之后不允许再修改运单了，因为报上去就异常
        List<HyShippingNote> shippingNoteList = hyShippingNoteService.list(new LambdaQueryWrapper<HyShippingNote>()
                .eq(HyShippingNote::getCompanyId, ShippingNoteDb.getCompanyId())
                .eq(HyShippingNote::getShippingStatus, ShippingStatus.已签收.getValue())
                .eq(HyShippingNote::getDelFlag, 0)
                .between(HyShippingNote::getCreateTime, DateUtil.offsetDay(new Date(), -90), new Date()));
        for (HyShippingNote note : shippingNoteList) {
            //排除相同运单
            if (ShippingNoteDb.getId().equals(note.getId())) {
                continue;
            }
            //如果是同一辆车或同一个司机
            if (ShippingNoteDb.getVehicleId().equals(note.getVehicleId()) || ShippingNoteDb.getDriverId().equals(note.getDriverId())) {
                //判断当前装卸货时间是否存在包含与被包含关系
                boolean isConflict = false;
                String errorMsg = StrUtil.EMPTY;
                //1.当前运单的装卸货时间段被其它运单包含
                if (ShippingNoteDb.getStatusDtLoading().after(note.getStatusDtLoading()) && ShippingNoteDb.getStatusDtUnloading().before(note.getStatusDtUnloading())) {
                    isConflict = true;
                    errorMsg = "当前运单" + ShippingNoteDb.getShippingNoteNumber() + "与运单" + note.getShippingNoteNumber() + "装卸货时间冲突";
                }
                //2.当前运单的装卸货时间段包含了其它运单
                else if (ShippingNoteDb.getStatusDtLoading().before(note.getStatusDtLoading()) && ShippingNoteDb.getStatusDtUnloading().after(note.getStatusDtUnloading())) {
                    isConflict = true;
                    errorMsg = "当前运单" + ShippingNoteDb.getShippingNoteNumber() + "与运单" + note.getShippingNoteNumber() + "装卸货时间冲突";
                }
                //3.当前运单的装货时间在其它运单装货-卸货时间段内
                else if (ShippingNoteDb.getStatusDtLoading().after(note.getStatusDtLoading()) && ShippingNoteDb.getStatusDtLoading().before(note.getStatusDtUnloading())) {
                    isConflict = true;
                    errorMsg = "当前运单" + ShippingNoteDb.getShippingNoteNumber() + "装货时间在运单" + note.getShippingNoteNumber() + "装卸货时间段内，运单业务异常";
                }
                //4.当前运单的卸货时间在其它运单装货-卸货时间段内
                else if (ShippingNoteDb.getStatusDtUnloading().after(note.getStatusDtLoading()) && ShippingNoteDb.getStatusDtLoading().before(note.getStatusDtUnloading())) {
                    isConflict = true;
                    errorMsg = "当前运单" + ShippingNoteDb.getShippingNoteNumber() + "卸货时间在运单" + note.getShippingNoteNumber() + "装卸货时间段内，运单业务异常";
                }
                //写入错误状态
                if (isConflict) {
                    ShippingNoteDb.setUploadStatus(AhUploadStatusEnum.UPLOAD_STEP3_ERROR.getStatus());
                    ShippingNoteDb.setUploadDate(new Date());
                    ShippingNoteDb.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_AH.getCode());
                    ShippingNoteDb.setReportFailureReason(errorMsg);
                    hyShippingNoteService.updateById(ShippingNoteDb);
                    log.error("安徽监管上报运单装卸货时间冲突, 上报运单{} {}-{} ----> 冲突运单{} {}-{}",
                            ShippingNoteDb.getShippingNoteNumber(),
                            DateUtils.dateTimeToString(ShippingNoteDb.getStatusDtLoading()),
                            DateUtils.dateTimeToString(ShippingNoteDb.getStatusDtUnloading()),
                            note.getShippingNoteNumber(),
                            DateUtils.dateTimeToString(note.getStatusDtLoading()),
                            DateUtils.dateTimeToString(note.getStatusDtUnloading()));
                    return Result.error(errorMsg);
                }
            }
        }

        //超载判断
        HyVehicle hyVehicle = this.vehicleService.getById(ShippingNoteDb.getVehicleId());
        if (ShippingNoteDb.getGoodsWeightLoading().compareTo(hyVehicle.getVehicleTonnage()) > 0 ) {
            ShippingNoteDb.setUploadStatus(AhUploadStatusEnum.UPLOAD_STEP3_ERROR.getStatus());
            ShippingNoteDb.setUploadDate(new Date());
            ShippingNoteDb.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_AH.getCode());
            ShippingNoteDb.setReportFailureReason("货物重量超过车辆核定载质量，货物重量: "+ShippingNoteDb.getGoodsWeightLoading()+"车辆核定载质量:"+hyVehicle.getVehicleTonnage());
            this.hyShippingNoteService.updateById(ShippingNoteDb);
            log.error("安徽监管上报超载 货物重量 {} > 核定载质量 {}", ShippingNoteDb.getGoodsWeightLoading(), hyVehicle.getVehicleTonnage());
            return Result.error("货物重量超过车辆核定载质量，货物重量:" + ShippingNoteDb.getGoodsWeightLoading() + " ,车辆核定载质量:" + hyVehicle.getVehicleTonnage());
        }

        //如果开启了实时上报
        //需要确认真实轨迹，需要再检验一次运单的运输车辆有没有轨迹（非要上报可以用模拟轨迹，将不再校验中交轨迹）
        //因为运单1和运单2如果开启了实时上报，在签收时和对账提交时，用的模拟运输距离
        String realtimeUpload = HyCfgUtil.getCfgItem2("anhui_report","realtime_upload");
        if (StrUtil.isNotEmpty(realtimeUpload)) {
            String vehicleTrackSwitch = this.settingService.getSettingValueByTag2("vehicle_track_switch");
            if ("1".equals(vehicleTrackSwitch)) {
                String startTime = DateUtils.dateTimeToString(hyShippingNote.getStatusDtReceive());
                String endTime = DateUtils.dateTimeToString(hyShippingNote.getStatusDtUnloading());
                String vehicleColor = StringUtils.isNotEmpty(hyVehicle.getVehiclePlateColorCode()) ? hyVehicle.getVehiclePlateColorCode() : "2";
                WaybillRouteVO waybillRouteVO = waybillRouteService.getWaybillRoute(hyVehicle.getVehicleNumber(), vehicleColor, startTime, endTime, "GCJ02");
                //如果轨迹是空或者是0km无法进行上报
                if (StrUtil.isEmpty(waybillRouteVO.getMileage()) || 0 == Double.valueOf(waybillRouteVO.getMileage()).intValue()) {
                    return Result.error("无法获取运单的运输距离，请检查中交车辆轨迹。");
                }

                log.info("安徽运单3上报，中交轨迹公里数{}", waybillRouteVO.getMileage());
            }
        }

        //先上传承运人信息
        Result resultActual = this.uploadActual(hyShippingNote.getDriverId(), hyShippingNote.getVehicleId());
        if (!resultActual.getCode().equals(CommonConstant.SC_OK_200)) {
            return resultActual;
        }

        ShippingNoteDTO shippingNoteDTO = baseReportService.shippingNoteTOShippingNoteDTOAhStep3(ShippingNoteDb);
        String postJsonString = JSONUtil.toJsonStr(shippingNoteDTO);
        String reporDocType = ReportDocTypeEnum.REPORT_DOC_TYPE_WLHY_YD3.getCode();
        ReportDocTypeEnum reportDocTypeEnum = ReportDocTypeEnum.getReportDocTypeEnumByVal(reporDocType);

        try{
            String reportResult = ahReportPlatformService.sendReport(reportDocTypeEnum, postJsonString, hyShippingNote.getShippingNoteNumber());
            if (StringUtils.isNotEmpty(reportResult)) {
                R result = JSON.parseObject(reportResult, R.class);
                boolean res = result.getCode() == 1001 && result.isSuccess() ? true : false;
                //上传运单第三步
                ShippingNoteDb.setUploadStatus(res ? AhUploadStatusEnum.UPLOAD_STEP3_SUCCESS.getStatus() : AhUploadStatusEnum.UPLOAD_STEP3_ERROR.getStatus());
                ShippingNoteDb.setReportFailureReason(res ? "" : result.getMsg()+result.getData());
                ShippingNoteDb.setUploadDate(new Date());
                ShippingNoteDb.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_AH.getCode());
                hyShippingNoteService.updateById(ShippingNoteDb);

                Thread.sleep(200);
                return res ? Result.OK("上报成功") : Result.error(result.getMsg());
            } else {
                throw new JeecgBootException("安徽监管平台响应报文错误");
            }
        } catch (Exception e) {
            e.printStackTrace();
            ShippingNoteDb.setUploadStatus(AhUploadStatusEnum.UPLOAD_STEP3_ERROR.getStatus());
            ShippingNoteDb.setReportFailureReason(e.getMessage());
            ShippingNoteDb.setUploadDate(new Date());
            ShippingNoteDb.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_AH.getCode());
            hyShippingNoteService.updateById(ShippingNoteDb);
        }

        return Result.error("上报数据传输失败");
    }


    /**
     * 平台司机上报
     *
     * @param driverId
     * @return
     */
    @Override
    public Result reportDriver(String driverId, String companyId) {

        HyDriver hyDriverDb = driverService.getById(driverId);
        if (hyDriverDb == null) {
            return Result.error("未找到对应数据");
        }

        HyDriverReport hyDriverReport = new HyDriverReport();
        try {
            //人员从业资格证验证
            if (!driverService.checkQualificationV2(hyDriverDb)) {
                throw new JeecgBootException("人员从业资格证验证号不正确或者已过期，请修改后重新上传！");
            }

            DriverDTO driverDTO = baseReportService.hyDriverTODriverDTO(hyDriverDb);
            String jsonString = JSONUtil.toJsonStr(driverDTO);
            String reporDocType = ReportDocTypeEnum.REPORT_DOC_TYPE_WLHY_JSY.getCode();
            ReportDocTypeEnum reportDocTypeEnum = ReportDocTypeEnum.getReportDocTypeEnumByVal(reporDocType);

            String reportResult = ahReportPlatformService.sendReport(reportDocTypeEnum, jsonString, "司机");
            if (StringUtils.isNotEmpty(reportResult)) {
                R result = JSON.parseObject(reportResult, R.class);
                boolean  res = result.getCode() == 1001 && result.isSuccess() ? true : false;
                hyDriverReport.setDriverId(driverId);
                hyDriverReport.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_AH.getCode());
                hyDriverReport.setDriverUploadStatus(res ? "1" : "2");
                hyDriverReport.setUploadDate( new Date() );
                hyDriverReport.setCompanyId(companyId);
                hyDriverReport.setDriverReportFailureReason(result.getMsg()+result.getData() );
                hyDriverReportService.saveDriverReport(hyDriverReport);

                this.driverService.updateAhUploadStatusById(driverId, hyDriverReport.getDriverUploadStatus());
                log.info("安徽监管更新司机上报回执信息, {}, {}", res, result.getMsg());

                return res ? Result.OK("上报成功") : Result.error(result.getMsg());
            } else {
                throw new JeecgBootException("未知异常");
            }
        } catch (Exception e){
            e.printStackTrace();
        }

        return Result.error("司机上报数据异常");
    }

    @Override
    public Result reportVehicle(String vehicleId, String companyId) {
        HyVehicle hyVehiclDb = vehicleService.getById(vehicleId);
        if(hyVehiclDb == null) {
            throw new JeecgBootException("未找到对应数据");
        }

        HyVehicleReport hyVehicleReport = new HyVehicleReport();
        if (StringUtils.isEmpty(hyVehiclDb.getRoadTransportNumber())) {
            throw new JeecgBootException("车辆道路运输证不能为空！");
        }

        if (!vehicleService.checkRTCNoV2(hyVehiclDb)) {
            throw new JeecgBootException("车辆道路运输证号不正确或者已过期，请修改后重新上传！");
        }

        List<HyVehicleType> hyVehicleTypeList = vehicleService.getHyVehicleByPid("1");
        HyVehicleType hyVehicleType = hyVehicleTypeList.stream().filter(s->hyVehiclDb.getVehicleType().contains(s.getText())).findAny().orElse(null);
        if (hyVehicleType == null) {
            throw new JeecgBootException("车辆类型不存在,修改后请重新上报");
        }
//        HyVehicleType hyVehicleType = vehicleService.getHyVehicleType(hyVehiclDb.getVehicleType());
//        if (hyVehicleType == null) {
//            throw new JeecgBootException("车辆类型不存在,修改后请重新上报！");
//        }

        //载重量上限判断
        if (hyVehiclDb.getVehicleTonnage().intValue() > 90) {
            throw new JeecgBootException("车辆的核载质量不在有效范围内");
        }

        //吨位上限判断
        if (hyVehiclDb.getGrossMass().intValue() > 90) {
            throw new JeecgBootException("车辆的总质量不在有效范围内");
        }

        if (hyVehiclDb.getVehicleTonnage().compareTo(hyVehiclDb.getGrossMass()) > -1) {
            throw new JeecgBootException("车辆的核载质量应小于车辆总吨位");
        }

        hyVehiclDb.setVehicleType(hyVehicleType.getValue());
        VehicleDTO vehicleDTO = baseReportService.hyVehicleDTOTOVehicleDTO(hyVehiclDb);
        String jsonString = JSONUtil.toJsonStr(vehicleDTO);
        String reporDocType = ReportDocTypeEnum.REPORT_DOC_TYPE_WLHY_CL.getCode();
        ReportDocTypeEnum reportDocTypeEnum = ReportDocTypeEnum.getReportDocTypeEnumByVal(reporDocType);

        try {
            String reportResult = ahReportPlatformService.sendReport(reportDocTypeEnum, jsonString, "车辆");
            if(StringUtils.isNotEmpty(reportResult)){
                R result = JSON.parseObject(reportResult, R.class);
                boolean res =  result.getCode() == 1001 && result.isSuccess() ?  true : false;
                hyVehicleReport.setVehicleId(vehicleId);
                hyVehicleReport.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_AH.getCode());
                hyVehicleReport.setVehicleUploadStatus(res ? "1" : "2");
                hyVehicleReport.setUploadDate( new Date() );
                hyVehicleReport.setCompanyId(companyId);
                hyVehicleReport.setVehicleReportFailureReason(result.getMsg()+result.getData());
                vehicleReportService.saveVehicleReport(hyVehicleReport);

                this.vehicleService.updateAhUploadStatusById(vehicleId, hyVehicleReport.getVehicleUploadStatus());
                log.info("安徽监管更新车辆上报回执信息, {}, {}", res, result.getMsg());

                return res ? Result.OK("上报成功") : Result.error(result.getMsg());
            } else {
                throw new JeecgBootException("未知异常");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return Result.error("车辆上报数据异常");
    }

    //上传实际承运人信息
    private Result uploadActual(String driverId, String vehicleId) {

        HyDriver hyDriver = this.driverService.getDriverById(driverId);
        if (null == hyDriver) {
            throw new JeecgBootException("未找到该运单绑定的司机");
        }

        HyVehicle hyVehicle = this.vehicleService.getById(vehicleId);
        if (null == hyVehicle) {
            throw new JeecgBootException("未找到该运单绑定的车辆");
        }

        ActualCarrierInfo actualCarrierInfo = new ActualCarrierInfo();
        if (hyVehicle.getOwner().contains("公司")) {
            actualCarrierInfo.setActualCarrierName(hyVehicle.getOwner() + "(" + hyDriver.getDriverName() + ")");
        } else {
            actualCarrierInfo.setActualCarrierName(hyDriver.getDriverName());
        }
        actualCarrierInfo.setActualCarrierBusinessLicense(
                StringUtils.isNotBlank(hyVehicle.getBusinessLicense()) ? hyVehicle.getBusinessLicense() :
                        hyVehicle.getRoadTransportNumber().substring(0, 6) + "000000"
        );
        actualCarrierInfo.setActualCarrierId(hyDriver.getIdcard());
        actualCarrierInfo.setActualCarrierID(hyDriver.getIdcard());

        String jsonString = JSONUtil.toJsonStr(actualCarrierInfo);
        String reporDocType = ReportDocTypeEnum.REPORT_DOC_TYPE_WLHY_CYR.getCode();
        ReportDocTypeEnum reportDocTypeEnum = ReportDocTypeEnum.getReportDocTypeEnumByVal(reporDocType);
        try {
            String reportResult = ahReportPlatformService.sendReport(reportDocTypeEnum, jsonString, "承运人");
            if (StringUtils.isNotEmpty(reportResult)) {
                R result = JSON.parseObject(reportResult, R.class);
                boolean res =  result.getCode() == 1001 && result.isSuccess() ?  true : false;
                log.info("安徽监管更新承运人上报回执信息, {}, {}", res, result.getMsg());

                return res ? Result.OK("上报成功") : Result.error("承运人上报失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return Result.error("承运人数据上报异常");
    }

    //安徽监管上报默认实际承运人为个人
    private void getAhActualCarrierInfo(String driverId, String vehicleId, ShippingNoteDTO shippingNoteDTO) {
        HyDriver hyDriver = driverService.getById(driverId);
        if (hyDriver == null) {
            throw new JeecgBootException("该运单司机信息不能为空");
        }

        HyVehicle hyVehicle = vehicleService.getById(vehicleId);
        if (hyVehicle == null) {
            throw new JeecgBootException("该运单车辆信息不能为空");
        }

        ActualCarrierInfo actualCarrierInfo = new ActualCarrierInfo();
        if (hyVehicle.getOwner().contains("公司")) {
            actualCarrierInfo.setActualCarrierName(hyVehicle.getOwner() + "(" + hyDriver.getDriverName() + ")");
        } else {
            actualCarrierInfo.setActualCarrierName(hyDriver.getDriverName());
        }

        actualCarrierInfo.setActualCarrierBusinessLicense(
                StringUtils.isNotBlank(hyVehicle.getBusinessLicense()) ? hyVehicle.getBusinessLicense() :
                        hyVehicle.getRoadTransportNumber().substring(0, 6) + "000000"
        );
        actualCarrierInfo.setActualCarrierId(hyDriver.getIdcard());
        actualCarrierInfo.setActualCarrierID(hyDriver.getIdcard());

        shippingNoteDTO.setActualCarrierInfo(actualCarrierInfo);
    }


    private void updateReportStatus(String shippingNoteNumber, String uploadStatus, String uploadFailureReason, Integer reportPlatformType) {

        this.hyShippingNoteService.update(new LambdaUpdateWrapper<HyShippingNote>()
                .eq(HyShippingNote::getShippingNoteNumber, shippingNoteNumber)
                .set(HyShippingNote::getUploadStatus, uploadStatus)
                .set(HyShippingNote::getReportFailureReason, uploadFailureReason)
                .set(HyShippingNote::getUploadDate, new Date())
                .set(HyShippingNote::getReportPlatformType, reportPlatformType)
        );

        return;
    }
}
